iT邦幫忙

2022 iThome 鐵人賽

DAY 24
0

昨天看完了簡單的useEffect,前天也看了useState,今天再來看點差不多簡單的:useRef

我們都是在要對某一HTML元素進行操作、或者是記住某個元素的reference時,才會使用到useRef。比方說對一個input進行聚焦(focus)、或者說在讀取完頁面時,對特定div使用element.scrollIntoView()讓div出現在畫面"中"等等的。

那我們來看看怎麼用吧:

import { useRef } from "react"

const App = () => {
  const inputRef = useRef(null)

  return <input type="text" ref={inputRef} />
}

export default App

好了,我們成功使用了useRef,TypeScript也沒有報錯。

那我們明天見~~~


開玩笑的,但useRef差不多就這麼簡單,TypeScript也真的不會報錯。
畢竟,TypeScript會自動幫我們推論inputRef的型別。
const inputRef: React.MutableRefObject<null>
我們得到的是一個MutableRefObject,也就是可變的Ref物件。
去看一下定義,你會得到:

    interface RefObject<T> {
        readonly current: T | null;
    }

發現了之前看過的唯讀關鍵字!以及current應該代表的型別必須是T或者null。
那我們缺什麼?我們最好主動帶給他一個型別,一個更精確的型別,上面泛型中的T,編輯器在後續的撰寫便能幫我們推薦更理想的屬性/方法:

const inputRef = useRef<HTMLInputElement>(null)
這時我們的inputRef就變成了下面這型別:
const inputRef: React.RefObject<HTMLInputElement>

舉例而言,如果我們要在元件渲染後,對input進行聚焦,就只要這樣:

useEffect(()=>{
    inputRef.current.focus()
},[])

但你如果實際這樣做的話,你會發現TypeScript報錯了,因為:
1.我們賦予inputRef的起始值是null
2.因為起始值是null,也就表示inputRef.current有可能是null
所以我們這邊要進行型別防衛,你可以:

  useEffect(() => {
    if (inputRef.current) {
      inputRef.current.focus()
    }
  }, [])
  
  //或者
  
  useEffect(() => {
      inputRef.current?.focus()
  }, [])
  
  //題外話,你也可以輸入
  //inputRef.current. 
  //看看編輯器提供了你哪些屬性/方法,滿好玩的

兩者都能達到效果,且編輯器也完全不會報錯。
你會發現這非常的簡單,簡單到有點不需要講,但我們透過查找定義、透過主動宣告型別,不僅了解了更多hook的內容,也得到了編輯器更多的幫助,長久下來必能節省我們寫code、debug的時間。

那今天就先講到這邊,非常建議你將ref放到不同的HTML element當中,看一下他會報出什麼錯、該怎麼修正?編輯器又會推薦哪些屬性/方法?

(寫的當下是連假第二天,趕快寫完才能趕快外出走走!)

附註:下面是編輯器會推薦的inputRef.current的屬性/方法

VSCode對inputRef推薦的屬性與方法
不曉得你有沒有注意過,清單當中的icon,藍色長方體icon是屬性property、紫色正方體icon是方法method。


上一篇
第23天!TypeScript 與 useEffect!
下一篇
第25天!TypeScript 與 useContext!
系列文
你也對開始使用typescript感到無力嗎?我也是 - 30天初探typescript30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言